#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：tools 
@File ：成品物料合同分配.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/11/18 下午3:27 
"""

"""
成品物料合同分配程序

输入：合同资源表路径，库存资源表路径，库存表完善字段列表，库存表匹配字段列表

处理逻辑：
1.分别读取合同表和资源表，逐行遍历库存资源表，根据库存表匹配字段列表，到合同资源表中进行数据筛选匹配
2.如果不存在匹配结果，那么跳过这行
3.如果存在一条匹配结果，则使用合同资源表中的字段完善库存表字段，范围是库存表完善字段列表中的字段
4.如果存在多条匹配结果，则在控制台进行打印合同数据，等待控制台输入选择之后，补全库存表
5.匹配的数据不再重复使用
"""

import os
import pandas as pd
import tkinter as tk
from tkinter import filedialog, simpledialog, messagebox


def read_data(file_path):
	"""
	根据文件扩展名读取数据，支持 CSV、XLS、XLSX 格式
	"""
	file_extension = os.path.splitext(file_path)[1].lower()
	if file_extension == '.csv':
		return pd.read_csv(file_path)
	elif file_extension in ['.xls', '.xlsx']:
		return pd.read_excel(file_path)
	else:
		raise ValueError(f"不支持的文件格式: {file_extension}")


def write_data(dataframe, output_path):
	"""
	将数据写入指定路径，格式为 XLSX
	"""
	dataframe.to_excel(output_path, index=False)


def select_path(title):
	"""
	打开文件选择对话框，返回选择的路径
	"""
	file_path = filedialog.askopenfilename(title=title, filetypes=[("All Files", "*.*"), ("CSV Files", "*.csv"),
																   ("Excel Files", "*.xls;*.xlsx")])
	return file_path


def match_and_complete(contract_df, inventory_df, complete_fields, match_fields):
	"""
	根据匹配字段进行筛选，并使用合同表数据完善库存表
	"""
	used_contract_indices = set()  # 记录已经使用过的合同表索引

	for index, inventory_row in inventory_df.iterrows():
		# 筛选出合同表中与当前库存表行匹配的数据
		filtered_contracts = contract_df
		for field in match_fields:
			filtered_contracts = filtered_contracts[filtered_contracts[field] == inventory_row[field]]

		if filtered_contracts.empty:
			# 没有匹配结果，跳过
			continue

		# 排除已经使用过的数据
		filtered_contracts = filtered_contracts.loc[~filtered_contracts.index.isin(used_contract_indices)]

		if filtered_contracts.empty:
			# 所有匹配结果都已经使用过，跳过
			continue

		elif len(filtered_contracts) == 1:
			# 仅有一条匹配结果，直接完善库存表
			contract_index = filtered_contracts.index[0]
			if contract_index not in used_contract_indices:
				inventory_df.loc[index, complete_fields] = filtered_contracts.loc[contract_index, complete_fields]
				used_contract_indices.add(contract_index)

		else:
			# 有多条匹配结果，弹出提示框并等待用户选择
			msg = f"库存行 {index} 匹配到的多条合同数据:\n\n"
			msg += filtered_contracts.to_string()
			msg += "\n\n请输入选择的合同行索引（输入 'p' 跳过）："
			user_input = simpledialog.askstring("多条匹配数据选择", msg)

			if user_input == 'p':
				# 跳过该行数据补全
				continue

			try:
				selected_index = int(user_input)
				if selected_index in filtered_contracts.index and selected_index not in used_contract_indices:
					inventory_df.loc[index, complete_fields] = filtered_contracts.loc[selected_index, complete_fields]
					used_contract_indices.add(selected_index)
				else:
					messagebox.showerror("错误", "选择无效，请检查输入！")
			except ValueError:
				messagebox.showerror("错误", "输入无效，请输入数字或 'p' 跳过！")

	return inventory_df


def main():
	# 创建主窗口
	root = tk.Tk()
	root.withdraw()  # 隐藏主窗口

	# 选择文件路径
	contract_path = select_path("请选择合同资源表路径")
	inventory_path = select_path("请选择库存资源表路径")
	if not contract_path or not inventory_path:
		messagebox.showwarning("警告", "未选择文件，程序终止！")
		return

	# 输入字段列表
	complete_fields = simpledialog.askstring("字段输入", "请输入库存表完善字段列表（用逗号分隔）:")
	match_fields = simpledialog.askstring("字段输入", "请输入库存表匹配字段列表（用逗号分隔）:")
	if not complete_fields or not match_fields:
		messagebox.showwarning("警告", "字段列表未填写完整，程序终止！")
		return

	complete_fields = [field.strip() for field in complete_fields.split(',')]
	match_fields = [field.strip() for field in match_fields.split(',')]

	try:
		# 读取数据
		contract_df = read_data(contract_path)
		inventory_df = read_data(inventory_path)

		# 处理并完善库存表
		updated_inventory = match_and_complete(contract_df, inventory_df, complete_fields, match_fields)

		# 保存更新后的库存表
		output_directory = os.path.dirname(inventory_path)
		output_path = os.path.join(output_directory, "result.xlsx")
		write_data(updated_inventory, output_path)
		messagebox.showinfo("完成", f"处理完成，更新后的库存表已保存至 {output_path}")
	except Exception as e:
		messagebox.showerror("错误", f"发生错误: {e}")


if __name__ == "__main__":
	main()
